package com.yami.shop.user.api.listener;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.app.param.PayInfoParam;
import com.yami.shop.bean.bo.PayInfoResultBO;
import com.yami.shop.bean.enums.PayEntry;
import com.yami.shop.bean.enums.PayStatus;
import com.yami.shop.bean.enums.ShopWalletChangeReason;
import com.yami.shop.bean.enums.UserBalanceLogType;
import com.yami.shop.bean.event.BalancePayEvent;
import com.yami.shop.bean.model.PayInfo;
import com.yami.shop.bean.model.ShopWallet;
import com.yami.shop.bean.model.UserExtension;
import com.yami.shop.bean.param.hnaPay.BaseTransForm;
import com.yami.shop.bean.pay.PayInfoDto;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.BeanUtil;
import com.yami.shop.config.HnaPayConfig;
import com.yami.shop.service.PayInfoService;
import com.yami.shop.service.ShopWalletLogService;
import com.yami.shop.service.ShopWalletService;
import com.yami.shop.service.UserExtensionService;
import com.yami.shop.user.common.model.UserBalanceLog;
import com.yami.shop.user.common.service.UserBalanceLogService;
import com.yami.shop.user.common.service.UserBalanceService;
import com.yami.shop.user.common.service.UserGasLogService;
import com.yami.shop.user.common.service.UserLevelService;
import lombok.AllArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * 余额支付操作
 *
 * @author lhd
 */
@Component("balanceListener")
@AllArgsConstructor
public class BalancePayListener {

    private final UserBalanceLogService userBalanceLogService;

    private final PayInfoService payInfoService;

    private final UserExtensionService userExtensionService;

    private final UserLevelService userLevelService;

    private final UserBalanceService userBalanceService;

    private final HnaPayConfig hnaPayConfig;

    private final UserGasLogService userGasLogService;

    private final ShopWalletService shopWalletService;

    private final ShopWalletLogService shopWalletLogService;

    @EventListener(BalancePayEvent.class)
    @Transactional(rollbackFor = Exception.class)
    public void balanceListener(BalancePayEvent event) {
        PayInfoDto payInfoDTO = event.getPayInfo();
        PayInfoParam payInfoParam = event.getPayInfoParam();
        PayInfo payInfo = payInfoService.getOne(new LambdaQueryWrapper<PayInfo>().eq(PayInfo::getPayNo, payInfoDTO.getPayNo()));
        Double amount = payInfo.getPayAmount();
        // 已经支付
        if (Objects.equals(payInfo.getPayStatus(), PayStatus.PAYED.value()) || Objects.equals(payInfo.getPayStatus(), PayStatus.REFUND.value())) {
            return;
        }
        // 余额支付 店铺余额or用户余额
        // 用户余额
        if(payInfoDTO.getPayUserType().equals("0")){
            UserExtension userExtension = userExtensionService.getOne(new LambdaQueryWrapper<UserExtension>().eq(UserExtension::getUserId, payInfo.getUserId()));
            if (Objects.isNull(userExtension)) {
                payInfoParam.setType(2);
                // 您的信息有误，请尝试刷新后再进行操作
                payInfoParam.setMessage(I18nMessage.getMessage("yami.information.is.wrong"));
                return;
            }
            if(Objects.isNull(userExtension.getTotalBalance()) || userExtension.getTotalBalance() < amount) {
                payInfoParam.setType(3);
                // 您的余额不足，请先充值余额
                payInfoParam.setMessage(I18nMessage.getMessage("yami.balance.is.insufficient"));
                return;
            }
            userExtension.setTotalBalance(Arith.sub(userExtension.getTotalBalance(), amount));
            userExtensionService.updateBalanceByVersion(userExtension);
            // 订单金额大于0，则添加余额记录
            if(amount > 0) {
                UserBalanceLog userBalanceLog = new UserBalanceLog();
                userBalanceLog.setUserId(payInfo.getUserId());
                if (Objects.equals(payInfo.getPayEntry(), PayEntry.VIP.value())){
                    // 购买会员
                    userBalanceLog.setType(UserBalanceLogType.BUY_MEMBER.value());
                } else if (Objects.equals(payInfo.getPayEntry(), PayEntry.RED_ENVELOPE.value())) {
                    // 发红包
                    userBalanceLog.setType(UserBalanceLogType.RED_PACKET_MONEY.value());
                    userBalanceLog.setBalanceId(Long.valueOf(payInfo.getOrderNumbers()));
                    userBalanceLog.setIsPayed(0);
                }  else if (Objects.equals(payInfo.getPayEntry(), PayEntry.GAS_RECHARGE.value())) {
                    // GAS充值
                    userBalanceLog.setType(UserBalanceLogType.BUY_GAS.value());
                } else {
                    // 购买行为的相关扣款
                    userBalanceLog.setType(UserBalanceLogType.PAY.value());
                }
                userBalanceLog.setIoType(0);
                userBalanceLog.setCreateTime(new Date());
                userBalanceLog.setChangeBalance(amount);
                userBalanceLog.setPayNo(payInfoDTO.getPayNo());
                userBalanceLogService.save(userBalanceLog);
            }
        }
        // 店铺余额
        if(payInfoDTO.getPayUserType().equals("1")){
            ShopWallet dbShopWallet = shopWalletService.getShopWalletByShopId(Long.valueOf(payInfoDTO.getBizUserId()));
            if (Objects.isNull(dbShopWallet)) {
                payInfoParam.setType(2);
                // 您的信息有误，请尝试刷新后再进行操作
                payInfoParam.setMessage(I18nMessage.getMessage("yami.information.is.wrong"));
                return;
            }

            if (amount > dbShopWallet.getSettledAmount()) {
                payInfoParam.setType(3);
                // 您的余额不足，请先充值余额
                payInfoParam.setMessage(I18nMessage.getMessage("yami.balance.is.insufficient"));
                return;
            }
            ShopWallet newShopWallet = BeanUtil.map(dbShopWallet, ShopWallet.class);
            newShopWallet.setSettledAmount(Arith.sub(dbShopWallet.getSettledAmount(), amount));
            // 乐观锁更新钱包信息
            if (!shopWalletService.updateById(newShopWallet)) {
                // 失败则抛异常
                // 服务器繁忙
                throw new YamiShopBindException("yami.network.busy");
            }
            // 订单金额大于0，则添加余额记录
            if(amount > 0) {
                shopWalletLogService.saveShopWalletLog(dbShopWallet, newShopWallet, ShopWalletChangeReason.GAS_CASH, payInfoDTO.getPayNo());
            }
        }
        String bizOrderNo = null;
        // 新生余额账户扣款逻辑
        if (!Objects.equals(payInfo.getPayEntry(), PayEntry.RED_ENVELOPE.value())){
            // 新生余额账户扣款逻辑
            BaseTransForm base = hnaPayConfig.getT003TransForm(payInfoDTO);
            try {
                Map<String, Object> post = hnaPayConfig.post(base);
                String respCode = post.get("resultCode").toString(); // 应答码
                if (respCode.equals("0000")) {
                    bizOrderNo = post.get("ncountOrderId").toString();
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        PayInfoResultBO payInfoResultBO = new PayInfoResultBO();
        payInfoResultBO.setIsPaySuccess(true);
        payInfoResultBO.setPayNo(payInfo.getPayNo());
        payInfoResultBO.setCallbackContent("余额支付成功");
        payInfoResultBO.setPayAmount(payInfo.getPayAmount());
        payInfoResultBO.setBizPayNo(payInfo.getPayNo());
        payInfoResultBO.setBizOrderNo(bizOrderNo);
        if (Objects.equals(payInfo.getPayEntry(), PayEntry.ORDER.value())) {
            // 订单支付回调
            payInfoService.noticeOrder(payInfoResultBO, payInfo);
        } else if (Objects.equals(payInfo.getPayEntry(), PayEntry.VIP.value())){
            // 购买会员回调
            userLevelService.noticeBuyVip(payInfoResultBO, payInfo);
        }else if (Objects.equals(payInfo.getPayEntry(), PayEntry.RED_ENVELOPE.value())){
            // 发红包回调
            userBalanceService.noticeRedEnvelope(payInfoResultBO, payInfo);
        }else if (Objects.equals(payInfo.getPayEntry(), PayEntry.GAS_RECHARGE.value())){
            // 购买Gas
            userGasLogService.noticeGasRecharge(payInfoResultBO, payInfo);
        }
        payInfoParam.setType(1);
    }
}
